worker: atomic quote claim, pipeline-wide revenue, image validation on update, crawler grid order - #32
Merged
Merged
Conversation
Aswincloud-Bot
approved these changes
Sep 3, 2026
Aswincloud-Bot
left a comment
There was a problem hiding this comment.
Auto-approved: @Aswinmcw is a member of @Aswincloud/admins.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
3d-printing | 502ba86 | Commit Preview URL Branch Preview URL |
Sep 03 2026, 09:48 AM |
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Sep 3, 2026
…venue, validate images on product update, match the crawler grid to the API order - handleQuotePaid read the quote, then wrote an order and marked the quote in one batch. Two deliveries of the same payment_link.paid — Razorpay retries, and the event-id header is not guaranteed — could both read order_id = NULL and both create an order, receipt, invoice and pair of emails. The quote is now claimed first with UPDATE … WHERE order_id IS NULL; only the delivery that changes a row goes on to write the order. A failed order write releases the claim so the retry can convert. - /api/admin/stats counted only 'paid' and 'shipped', so revenue dropped the moment an order went to "in production" and came back when it shipped. Every stage from paid to delivered counts; cancelled/refunded/pending do not. - updateProduct accepted any string for image/images — an external URL, a traversal, a typo — where createProduct checks the manifest. Same check now. - The homepage's server-rendered grid used ORDER BY sort, name; the API orders pinned → buyable → quote-only. A crawler indexed one order and the visitor watched it reshuffle when main.js ran. Same order on both. Co-authored-by: Cursor <cursoragent@cursor.com>
Aswinmcw
force-pushed
the
fix/worker-money-idempotency
branch
from
September 3, 2026 09:47
02d8a4a to
502ba86
Compare
Aswinmcw
enabled auto-merge
September 3, 2026 09:47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Server-side correctness fixes from the review. No API shape changes.
payment_link.paid.handleQuotePaiddid SELECT quote → batch(INSERT order, INSERT item, UPDATE quote). Two deliveries of the same event (Razorpay retries;x-razorpay-event-idis not guaranteed to be present) could both pass thequote.order_idcheck and both create an order, receipt, invoice and customer/owner emails for a single payment. The quote is now claimed first withUPDATE quotes … WHERE id = ? AND order_id IS NULL; a delivery that changes 0 rows stops before writing anything. If the order write then fails, the claim is released so the retry converts the quote instead of leaving it marked paid with a danglingorder_id.stats()summedstatus IN ('paid','shipped'), so marking an order "In production" or "Ready" removed it from the dashboard's revenue and order count until it shipped, and "Delivered" removed it again. Now countspaid, in_production, ready, shipped, delivered.createProductchecksimage/imagesagainstassets/images.json;updateProductaccepted any string (external URL,../, a filename that does not exist) and stored it verbatim, to be rendered as<img src>on the storefront. The update path now applies the same manifest check and stores canonicalassets/images/<file>paths.ORDER BY sort, namewhile/api/productsorders pinned → buyable → quote-only with a different SQL order, so the indexed grid and the visible grid differed and the page visibly reshuffled when JS ran. Both now use the same ordering.Test plan
npm testgreen (orders 204, admin 428)https://…,//…,../…and unknown files, accepts and canonicalises manifest filesMade with Cursor